package oss.juelg.flashlight_mini;

//FIXME: galaxy ace: fehlt lediglich TORCH? oder TORCH vorhanden, aber funktioniert nicht?
//TODO: make activity create white background, if active and torch missing?

/*
11-14 18:07:29.123 D/DOMX    (144): ERROR: failed check:(eError == OMX_ErrorNone) || (eError == OMX_ErrorNoMore) - returning error: 0x80001005 - Error returned from OMX API in ducati
11-14 18:07:29.123 E/CameraHAL(144): Error while configuring rotation 0x80001005
11-14 18:07:29.295 D/DOMX    (144): ERROR: failed check:(eError == OMX_ErrorNone) || (eError == OMX_ErrorNoMore) - returning error: 0x80001005 - Error returned from OMX API in ducati
11-14 18:07:29.295 E/CameraHAL(144): Error while configuring rotation 0x80001005

D/CameraSettings( 2564): Parameters: [antibanding-values=... enthält rotation =...


auf galaxy s2: einschalten
12-17 09:16:28.200: D/flashlight(5171): flash was: off
12-17 09:16:28.205: D/flashlight(5171): toggleCameraFlash: now torch
12-17 09:16:28.205: D/SecCameraHardware(1823): int android::HAL_camera_device_set_parameters(camera_device*, const char*)
12-17 09:16:28.210: D/ISecCameraHardware(1823): setParameters X: success
12-17 09:16:28.210: D/SecCameraHardware(1823): LSIHAL int android::HAL_camera_device_preview_enabled(camera_device*)
12-17 09:16:28.210: D/SecCameraHardware(1823): LSIHAL int android::HAL_camera_device_set_preview_window(camera_device*, preview_stream_ops*)
12-17 09:16:28.210: D/ISecCameraHardware(1823): virtual android::status_t android::ISecCameraHardware::setPreviewWindow(preview_stream_ops*): mPreviewWindow 0x0
12-17 09:16:28.210: E/ISecCameraHardware(1823): preview window is NULL!
12-17 09:16:28.210: D/SecCameraCoreManager(1823): virtual android::status_t android::SecCameraCoreManager::startPreview():start IT Policy checking thread
12-17 09:16:28.220: D/ShotCommon(1823): InitFaceTracking Success
12-17 09:16:28.220: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_enable_msg_type(camera_device*, int32_t)
12-17 09:16:28.220: D/SecCameraHardware(1823): LSIHAL int android::HAL_camera_device_start_preview(camera_device*)
12-17 09:16:28.220: D/ISecCameraHardware(1823): startPreview E
12-17 09:16:28.220: D/SecCameraHardware(1823): nativeStartPreview E
12-17 09:16:28.220: D/SecCameraHardware(1823): virtual android::status_t android::SecCameraHardware::nativeStartPreview(): mPreviewFormat = NV21
12-17 09:16:28.225: D/SecCameraHardware(1823): allocatePreviewHeap: 640x480, frame 460800x8
12-17 09:16:28.485: D/SecCameraHardware(1823): nativeStartPreview X
12-17 09:16:28.485: D/ISecCameraHardware(1823): startPreview X
12-17 09:16:29.230: I/InputReader(1990): Touch event's action is 0x0 (deviceType=0) [pCnt=1, pending(waiting finished signal)=0, s=0.2732 ]
12-17 09:16:29.230: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x0
12-17 09:16:29.230: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x0
12-17 09:16:29.230: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x0
12-17 09:16:29.305: I/InputReader(1990): Touch event's action is 0x1 (deviceType=0) [pCnt=1, pending(waiting finished signal)=0, s=]
12-17 09:16:29.305: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x1
12-17 09:16:29.305: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x1
12-17 09:16:29.305: I/InputDispatcher(1990): Delivering touch to current input target: action: 0x1
12-17 09:16:29.320: D/flashlight(5171): onStartCommand(Intent: Intent { act=oss.juelg.flashlight_mini.FLASH_INTENT flg=0x10000000 bnds=[8,346][112,450] (has extras) }, data: null)
12-17 09:16:29.320: D/flashlight(5171): onStartCommand(Intent extras size: 1
12-17 09:16:29.320: D/flashlight(5171): onStartCommand(Intent extra policy: null
12-17 09:16:29.320: D/flashlight(5171): onStartCommand(Intent extra flash: TOGGLE
12-17 09:16:29.325: D/flashlight(5171): onStartCommand() done
12-17 09:16:29.365: D/flashlight(5171): flash was: torch

ausschalten:
12-17 09:16:29.365: D/flashlight(5171): flash was: torch
12-17 09:16:29.370: D/flashlight(5171): toggleCameraFlash: now off
12-17 09:16:29.375: D/SecCameraHardware(1823): int android::HAL_camera_device_set_parameters(camera_device*, const char*)
12-17 09:16:29.380: D/ISecCameraHardware(1823): setParameters X: success
12-17 09:16:29.380: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_disable_msg_type(camera_device*, int32_t)
12-17 09:16:29.380: D/SecCameraCoreManager(1823): virtual void android::SecCameraCoreManager::stopPreview():stop IT Policy checking thread
12-17 09:16:29.430: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_stop_preview(camera_device*)
12-17 09:16:29.430: D/ISecCameraHardware(1823): stopPreview E
12-17 09:16:29.460: D/SecCameraHardware(1823): nativeStopPreview EX
12-17 09:16:29.460: D/ISecCameraHardware(1823): stopPreview X
12-17 09:16:29.460: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_disable_msg_type(camera_device*, int32_t)
12-17 09:16:29.465: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_disable_msg_type(camera_device*, int32_t)
12-17 09:16:29.465: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_stop_preview(camera_device*)
12-17 09:16:29.465: D/ISecCameraHardware(1823): stopPreview E
12-17 09:16:29.465: W/ISecCameraHardware(1823): stopPreview: warning, preview has been stopped
12-17 09:16:29.465: D/SecCameraHardware(1823): LSIHAL int android::HAL_camera_device_cancel_picture(camera_device*)
12-17 09:16:29.465: D/ISecCameraHardware(1823): cancelPicture EX
12-17 09:16:29.465: D/SecCameraCoreManager(1823): virtual void android::SecCameraCoreManager::release(): release IT policy checking thread
12-17 09:16:29.465: D/SecCameraHardware(1823): LSIHAL void android::HAL_camera_device_release(camera_device*)
12-17 09:16:29.465: D/SecCameraHardware(1823): release E
12-17 09:16:29.500: I/SecCameraCoreManager(1823): SecCameraCoreManager destroyed: pid=1823
12-17 09:16:29.500: I/ShotSingle(1823): ShotSingle destroyed: pid=1823
12-17 09:16:29.505: I/ShotCommon(1823): ShotCommon destroyed: pid=1823
12-17 09:16:29.505: I/SecCameraCoreManager(1823): SecCameraCoreManager destroyed: before mHardware.clear()
12-17 09:16:29.505: I/SecCameraCoreManager(1823): Destroying camera 0
12-17 09:16:29.505: I/SecCameraHardware(1823): int android::HAL_camera_device_close(hw_device_t*)
12-17 09:16:29.505: I/SecCameraCoreManager(1823): SecCameraCoreManager destroyed: after mHardware.clear()


 */

import static oss.juelg.flashlight_mini.FlashlightActivity.TAG;

import java.util.concurrent.LinkedBlockingQueue;

import oss.juelg.flashlight_mini.FlashState.ReleasePolicy;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.util.Log;

/**
 * worker thread managing the camera
 * 
 * symchronizes using stateList
 */
class CameraThread implements Runnable {

	private LinkedBlockingQueue<FlashState> stateList;

	/**
	 * @param flashlightService
	 */
	CameraThread(LinkedBlockingQueue<FlashState> stateList) {
		this.stateList = stateList;
	}

	private boolean flashActive = false;
	private Camera cam;

	@Override
	public void run() {
		// may be useless
		synchronized (getClass()) { // ensure previous worker thread
									// finishes
			Log.d(TAG, "run()");
			// reorder while/try for efficiency?
			try {
				while (!Thread.interrupted()) { // until interrupt()
					FlashState newState = stateList.take();

					if (cam == null && newState.policy == ReleasePolicy.LAZY) {
						openCam();
						if (flashActive) {
							Log.e(TAG,
									"cameraThread: unexpected camera state: flashactive && cam == null");
						}
					}

					if (newState.mode != flashActive) {
						toggleCameraFlash(newState);
						if (newState.mode) {
							cam.startPreview();
						} else {
							cam.stopPreview();
						}
					}

					if (cam != null && !flashActive
							&& newState.policy == ReleasePolicy.EAGER) {
						releaseCam();
					}
				}
			} catch (InterruptedException e) {
				Log.d(TAG, "run(): interrupted");
				return;
			} finally {
				releaseCam();
			}
			Log.e(TAG, "run(): interrupted outside of acquire");
		}
	}

	private void toggleCameraFlash(FlashState newState) {
		Parameters params;
		boolean wasTorch;
		String newMode;

		if (cam == null) {
			boolean cameraReady = openCam();
			if (!cameraReady) {
				Log.e(TAG, "toggleCameraFlash: open failed");
				return;
			}
		}

		// cam was acquired
		params = cam.getParameters();
		String oldMode = params.getFlashMode(); //can return null

		if (oldMode != null) {

			Log.d(TAG, "flash was: " + oldMode);

			wasTorch = oldMode.equals(Parameters.FLASH_MODE_TORCH);

			// true if torch, else false
			if (wasTorch != flashActive) {
				Log.e(TAG, "toggleCameraFlash: expected flash " + flashActive
						+ ", was: " + wasTorch);
			}
			
		} else {
			Log.e(TAG, "toggleCameraFlash: flash mode setting not supported");
			return;
		}

		// // TODO: evaluate available flash modes
		// List<String> strings = params.getSupportedFlashModes();
		// if (strings != null) {
		// for (String s : strings)
		// Log.v(TAG, "supported flash mode: " + s);
		// } else {
		// Log.v(TAG, "no flash mode supported");
		// }

		newMode = (wasTorch) ? Parameters.FLASH_MODE_OFF
				: Parameters.FLASH_MODE_TORCH;
		flashActive = !wasTorch;

		Log.d(TAG, "toggleCameraFlash: now " + newMode);
		params.setFlashMode(newMode);
		cam.setParameters(params);

		// send status info to widget?
	}

	private void releaseCam() {
		if (cam != null) {
			cam.release();
			cam = null;
		}
	}

	private boolean openCam() {
		if (cam == null) {
			try {
				cam = android.hardware.Camera.open();
			} catch (RuntimeException re) {
				Log.e(TAG,
						"run(): open threw RuntimeException: "
								+ re.getMessage(), re);
				return false; // cam not initialized
			}
		}
		return true;
	}

}